package com.coursehub.course.service.impl;

import com.coursehub.course.dto.ClassesCreateDto;
import com.coursehub.course.entity.Classes;
import com.coursehub.course.entity.ClassesStudent;
import com.coursehub.course.entity.ClassesStudentId;
import com.coursehub.course.entity.ClassesTeacher;
import com.coursehub.course.entity.ClassesTeacherId;
import com.coursehub.course.repository.ClassesRepository;
import com.coursehub.course.repository.ClassesStudentRepository;
import com.coursehub.course.repository.ClassesTeacherRepository;
import com.coursehub.course.service.ClassesService;
import com.coursehub.course.service.CourseService;
import com.coursehub.shared.exception.BusinessException;
import com.coursehub.shared.exception.ResourceNotFoundException;
import com.coursehub.shared.util.StringUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

/**
 * 班级服务实现类
 */
@Service
@RequiredArgsConstructor
@Transactional
public class ClassesServiceImpl implements ClassesService {
    
    private static final Logger log = LoggerFactory.getLogger(ClassesServiceImpl.class);
    
    private final ClassesRepository classesRepository;
    private final ClassesStudentRepository classesStudentRepository;
    private final ClassesTeacherRepository classesTeacherRepository;
    private final CourseService courseService;
    
    @Override
    public Classes createClass(ClassesCreateDto createDto) {
        log.info("创建班级: {}", createDto.getClassesName());
        
        // 验证课程是否存在
        if (!courseService.existsByCourseId(createDto.getCourseId())) {
            throw new BusinessException("课程不存在: " + createDto.getCourseId());
        }
        
        // 验证同一课程下班级名称是否已存在
        if (classesRepository.findByCourseIdAndClassesName(createDto.getCourseId(), createDto.getClassesName()).isPresent()) {
            throw new BusinessException("该课程下班级名称已存在: " + createDto.getClassesName());
        }
        
        // 创建班级实体
        Classes classes = new Classes();
        classes.setClassesId(UUID.randomUUID().toString());
        classes.setClassesName(createDto.getClassesName());
        classes.setCourseId(createDto.getCourseId());
        classes.setDescription(createDto.getDescription());
        
        Classes savedClasses = classesRepository.save(classes);
        log.info("班级创建成功: {}", savedClasses.getClassesId());
        
        return savedClasses;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Classes getClassById(String classesId) {
        return classesRepository.findById(classesId)
                .orElseThrow(() -> new ResourceNotFoundException("Classes", classesId));
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Classes> getAllClasses() {
        return classesRepository.findAll();
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Classes> getClassesByCourseId(String courseId) {
        return classesRepository.findByCourseId(courseId);
    }
    
    @Override
    public Classes updateClass(String classesId, ClassesCreateDto updateDto) {
        log.info("更新班级: {}", classesId);
        
        Classes existingClasses = getClassById(classesId);
        
        // 如果要更新班级名称，检查新名称在同一课程下是否已存在
        if (StringUtils.isNotBlank(updateDto.getClassesName()) && 
            !updateDto.getClassesName().equals(existingClasses.getClassesName())) {
            if (classesRepository.findByCourseIdAndClassesName(existingClasses.getCourseId(), updateDto.getClassesName()).isPresent()) {
                throw new BusinessException("该课程下班级名称已存在: " + updateDto.getClassesName());
            }
        }
        
        // 更新班级信息
        if (StringUtils.isNotBlank(updateDto.getClassesName())) {
            existingClasses.setClassesName(updateDto.getClassesName());
        }
        if (updateDto.getDescription() != null) {
            existingClasses.setDescription(updateDto.getDescription());
        }
        
        Classes updatedClasses = classesRepository.save(existingClasses);
        log.info("班级更新成功: {}", classesId);
        
        return updatedClasses;
    }
    
    @Override
    public void deleteClass(String classesId) {
        log.info("删除班级: {}", classesId);
        
        if (!classesRepository.existsByClassesId(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        
        classesRepository.deleteById(classesId);
        log.info("班级删除成功: {}", classesId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean existsByClassesId(String classesId) {
        return StringUtils.isNotBlank(classesId) && classesRepository.existsByClassesId(classesId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean existsByClassesName(String classesName) {
        return StringUtils.isNotBlank(classesName) && classesRepository.existsByClassesName(classesName);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Classes> searchClassesByName(String classesName) {
        return classesRepository.findByClassesNameContaining(classesName);
    }
    
    @Override
    public String getCourseIdByClassId(String classesId) {
        log.info("根据班级ID获取课程ID: {}", classesId);
        Classes classes = getClassById(classesId);
        return classes.getCourseId();
    }
    
    @Override
    public List<String> getStudentIdsByClassId(String classesId) {
        log.info("根据班级ID获取学生ID列表: {}", classesId);
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        return classesStudentRepository.findStudentIdsByClassesId(classesId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getTeacherIdsByClassId(String classesId) {
        log.info("根据班级ID获取教师ID列表: {}", classesId);
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        return classesTeacherRepository.findTeacherIdsByClassesId(classesId);
    }
    
    @Override
    public void addStudentToClass(String classesId, String userId) {
        log.info("向班级添加学生: classesId={}, userId={}", classesId, userId);
        
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        
        // 检查学生是否已在班级中
        if (classesStudentRepository.existsById_ClassesIdAndId_UserId(classesId, userId)) {
            throw new BusinessException("学生已在该班级中: " + userId);
        }
        
        // 创建班级学生关联
        ClassesStudentId id = new ClassesStudentId(userId, classesId);
        
        // 设置班级关联
        Classes classes = classesRepository.findById(classesId)
            .orElseThrow(() -> new ResourceNotFoundException("Classes", classesId));
        ClassesStudent classesStudent = new ClassesStudent(id, classes);
        
        classesStudentRepository.save(classesStudent);
        log.info("成功向班级添加学生: classesId={}, userId={}", classesId, userId);
    }
    
    @Override
    public void removeStudentFromClass(String classesId, String userId) {
        log.info("从班级移除学生: classesId={}, userId={}", classesId, userId);
        
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        
        // 检查学生是否在班级中
        ClassesStudentId id = new ClassesStudentId(userId, classesId);
        
        if (!classesStudentRepository.existsById(id)) {
            throw new BusinessException("学生不在该班级中: " + userId);
        }
        
        classesStudentRepository.deleteById(id);
        log.info("成功从班级移除学生: classesId={}, userId={}", classesId, userId);
    }
    
    @Override
    public void addTeacherToClass(String classesId, String userId) {
        log.info("向班级添加教师: classesId={}, userId={}", classesId, userId);
        
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        
        // 检查教师是否已在班级中
        if (classesTeacherRepository.existsById_ClassesIdAndId_UserId(classesId, userId)) {
            throw new BusinessException("教师已在该班级中: " + userId);
        }
        
        // 创建班级教师关联
        ClassesTeacherId id = new ClassesTeacherId(classesId, userId);
        
        // 设置班级关联
        Classes classes = classesRepository.findById(classesId)
            .orElseThrow(() -> new ResourceNotFoundException("Classes", classesId));
        ClassesTeacher classesTeacher = new ClassesTeacher(id, classes);
        
        classesTeacherRepository.save(classesTeacher);
        log.info("成功向班级添加教师: classesId={}, userId={}", classesId, userId);
    }
    
    @Override
    public void removeTeacherFromClass(String classesId, String userId) {
        log.info("从班级移除教师: classesId={}, userId={}", classesId, userId);
        
        // 验证班级是否存在
        if (!classesRepository.existsById(classesId)) {
            throw new ResourceNotFoundException("Classes", classesId);
        }
        
        // 检查教师是否在班级中
        ClassesTeacherId id = new ClassesTeacherId(classesId, userId);
        
        if (!classesTeacherRepository.existsById(id)) {
            throw new BusinessException("教师不在该班级中: " + userId);
        }
        
        classesTeacherRepository.deleteById(id);
        log.info("成功从班级移除教师: classesId={}, userId={}", classesId, userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isStudentInClass(String classesId, String userId) {
        return classesStudentRepository.existsById_ClassesIdAndId_UserId(classesId, userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isTeacherInClass(String classesId, String userId) {
        return classesTeacherRepository.existsById_ClassesIdAndId_UserId(classesId, userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Classes> getClassesAsTeacher(String courseId, String userId) {
        log.info("获取用户作为教师的班级列表: courseId={}, userId={}", courseId, userId);
        
        List<ClassesTeacher> classesTeachers = classesTeacherRepository.findByCourseIdAndUserId(courseId, userId);
        return classesTeachers.stream()
                .map(ClassesTeacher::getClasses)
                .collect(java.util.stream.Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public String getClassesIdByCourseAndUser(String courseId, String userId) {
        log.info("获取用户在课程下的班级ID: courseId={}, userId={}", courseId, userId);
        
        // 首先检查用户是否为该课程下某个班级的教师
        List<ClassesTeacher> teacherClasses = classesTeacherRepository.findByCourseIdAndUserId(courseId, userId);
        if (!teacherClasses.isEmpty()) {
            return teacherClasses.get(0).getClasses().getClassesId();
        }
        
        // 如果不是教师，检查是否为学生
        List<Classes> courseClasses = classesRepository.findByCourseId(courseId);
        for (Classes classes : courseClasses) {
            if (classesStudentRepository.existsById_ClassesIdAndId_UserId(classes.getClassesId(), userId)) {
                return classes.getClassesId();
            }
        }
        
        return null; // 用户既不是教师也不是学生
    }
}